//
//  BKWebViewController.m
//  XPhoto
//
//  Created by baboy on 2019/4/26.
//  Copyright © 2019 baboy. All rights reserved.
//

#import "BKWebViewController.h"
#import "BKHttpRequestManager.h"
#import "NSArray+x.h"
#import "NSDictionary+x.h"
#import <BKKit/ThemeFactory.h>
#import <BKKit/BKApi.h>
#import "SysDict.h"
#import "User.h"

#define EXE_WEB_JS(webView, jsStr) [webView evaluateJavaScript:jsStr completionHandler:nil];
#define INJECT_HEADER_FLAG_KEY  @"X-APP-ID"
#define INJECT_CTX_KEY          @"_APP_CTX_"

static NSMutableDictionary *_injectedUserInfo = nil;
static NSDictionary *_injectedCookies = nil;

@interface BKWebViewController ()
@property(nonatomic, strong) IBOutlet UIProgressView *progressView;
@property(nonatomic, strong) IBOutlet UIView *bottomView;
@property(nonatomic, strong) IBOutlet UIButton *backButton;
@property(nonatomic, strong) IBOutlet UIButton *forwardButton;
@property(nonatomic, strong) IBOutlet NSLayoutConstraint *webViewBottomConstraint;

- (IBAction)goBack:(id)sender;
- (IBAction)goForward:(id)sender;
@end

@implementation BKWebViewController
+ (void)initialize {
    if (!_injectedUserInfo) {
        _injectedUserInfo = [[NSMutableDictionary alloc] init];
    }
}
- (instancetype)init{
    if (self = [super initWithNibName:NSStringFromClass([self class]) bundle:nil]) {
    }
    return self;
}
- (instancetype)initWithConfiguration:(NSDictionary *)configuration{
    if (self = [self init]) {
        self.configuration = configuration;
    }
    return self;
}

+ (void)injectUserInfo:(NSDictionary *)userInfo cookies:(NSDictionary *)cookies forHosts:(NSArray *)hosts{
    _injectedUserInfo[BK_WEB_INJECTED_DATA_HOST_KEY] = hosts;
    _injectedUserInfo[BK_WEB_INJECTED_DATA_USERINFO_KEY] = userInfo;
    _injectedCookies = cookies;
}
- (NSMutableURLRequest *)injectHeadersForRequest:(NSURLRequest *)request{
    NSArray *injectedHosts = _injectedUserInfo[BK_WEB_INJECTED_DATA_HOST_KEY];
    if ( injectedHosts && [injectedHosts containsObject:request.URL.host]) {
        id flag = [request.allHTTPHeaderFields valueForKey:INJECT_HEADER_FLAG_KEY];
        if (flag) {
            return nil;
        }
        NSDictionary *userInfo = _injectedUserInfo[BK_WEB_INJECTED_DATA_USERINFO_KEY];
        NSDictionary *headers = userInfo[BK_WEB_INJECTED_DATA_USERINFO_HEADER_KEY];
        if (headers) {
            NSMutableURLRequest *mutableRequest = nil;
            if ([request isMemberOfClass:[NSMutableURLRequest class]]) {
                mutableRequest = (NSMutableURLRequest *)request;
            }else{
                mutableRequest = [request mutableCopy];
            }
            for (NSString *k in headers.allKeys) {
                id v = [headers valueForKey:k];
                NSString *headerKey = [NSString stringWithFormat:@"X-%@", [k capitalizedString]];
                [mutableRequest setValue:v forHTTPHeaderField:headerKey];
            }
            [mutableRequest setValue:APP_ID forHTTPHeaderField:INJECT_HEADER_FLAG_KEY];
            return mutableRequest;
        }
    }
    return nil;
}
- (WKWebView *)webView{
    if (!_webView) {
        CGRect frame = self.view.bounds;
        frame.size.height -= 80;
        _webView= [[WKWebView alloc] initWithFrame:frame];
        [self.view addSubview:_webView];
        [self setupWebviewConfiguration];
    }
    return _webView;
}
- (void)setupWebviewConfiguration{

    NSMutableArray *scripts = [NSMutableArray array];
    [scripts addObject:@"window.AppCtx=window.webkit.messageHandlers.AppCtx"];
    
    if (_injectedCookies) {
        for (NSString *k in _injectedCookies.allKeys) {
            NSString *v = _injectedCookies[k];
            if (v) {
                [scripts addObject:[NSString stringWithFormat:@"document.cookie='%@=%@;path=/'", k, v ] ];
            }
        }
    }

    NSDictionary *userInfo = _injectedUserInfo[BK_WEB_INJECTED_DATA_USERINFO_KEY];
    NSMutableDictionary *ctx = [NSMutableDictionary dictionary];
    for (NSString *k in userInfo.allKeys) {
        id v = userInfo[k];
        if ([v respondsToSelector:@selector(dict)]) {
            v = [v dict];
        }
        ctx[k] = v;
    }
    
    [scripts addObject:[NSString stringWithFormat:@"window.%@=%@;", INJECT_CTX_KEY, [ctx jsonString]] ];
    [scripts addObject:@""];
    WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[scripts componentsJoinedByString:@";"]
                                                         injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    
    
    [_webView.configuration.userContentController addUserScript: cookieScript];
    [_webView.configuration.userContentController addScriptMessageHandler:self name:@"AppCtx"];
    _webView.UIDelegate = self;
    _webView.navigationDelegate = self;
    [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    [_webView addObserver:self forKeyPath:@"canGoBack" options:NSKeyValueObservingOptionNew context:nil];
    [_webView addObserver:self forKeyPath:@"canGoForward" options:NSKeyValueObservingOptionNew context:nil];
    
}
- (void)setCurrentURL:(NSURL *)currentURL{
    if ([currentURL.absoluteString isEqualToString:_currentURL.absoluteString]) {
        return;
    }
    _currentURL = currentURL;
    if (currentURL && _webView) {
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.currentURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:120];
        [self.webView loadRequest:request];
    }
}
- (void)viewSafeAreaInsetsDidChange{
    [super viewSafeAreaInsetsDidChange];
    DLOG(@"%@,%@,%@,%@", NSStringFromUIEdgeInsets([self additionalSafeAreaInsets]),NSStringFromCGRect(self.view.frame),NSStringFromUIEdgeInsets(self.view.safeAreaInsets), NSStringFromDirectionalEdgeInsets(self.systemMinimumLayoutMargins));
    
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.edgesForExtendedLayout = UIRectEdgeNone;
    self.navigationController.navigationBar.translucent = NO;
    self.navigationItem.leftBarButtonItem  =[ThemeFactory navBarButtonForKey:@"navigationbar-back-button" withTarget:self action:@selector(close:)];;
    [self setupWebviewConfiguration];
    if (self.currentURL) {
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.currentURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:120];
        [self injectHeadersForRequest:request];
        [self.webView loadRequest:request];
    }
}
- (void)close:(id)sender{
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if (object == self.webView && [keyPath isEqualToString:@"estimatedProgress"]) {
        CGFloat newprogress = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
        self.progressView.alpha = 1.0f;
        [self.progressView setProgress:newprogress animated:YES];
        if (newprogress >= 1.0f) {
            [UIView animateWithDuration:0.3f
                                  delay:0.3f
                                options:UIViewAnimationOptionCurveEaseOut
                             animations:^{
                                 self.progressView.alpha = 0.0f;
                             }
                             completion:^(BOOL finished) {
                                 [self.progressView setProgress:0 animated:NO];
                             }];
        }
        return;
    }
    if (object == self.webView && ( [keyPath isEqualToString:@"canGoBack"] || [keyPath isEqualToString:@"canGoForward"] ) ) {
        [self refreshBottomView];
        return;
    }
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
- (void)refreshBottomView{
    self.backButton.enabled = self.webView.canGoBack;
    self.forwardButton.enabled = self.webView.canGoForward;
    self.bottomView.hidden = !self.webView.canGoBack && !self.webView.canGoForward;
    self.webViewBottomConstraint.constant = self.bottomView.hidden ? 0 : - (self.view.safeAreaInsets.bottom + self.bottomView.bounds.size.height);
}

- (IBAction)goBack:(id)sender{
    @synchronized (self) {
        if (self.webView.canGoBack) {
            [self.webView goBack];
        }
    }
}
- (IBAction)goForward:(id)sender{
    @synchronized (self) {
        if (self.webView.canGoForward) {
            [self.webView goForward];
        }
    }
}
#pragma mark WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    DLOG(@"%@", navigationAction.request.URL);
    NSURLRequest *newRequest =  [self injectHeadersForRequest:navigationAction.request];
    if (newRequest) {
        [webView loadRequest:newRequest];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    //EXE_WEB_JS(webView, @"document.documentElement.style.webkitTouchCallout = 'none';");
    DLOG(@"");
    
}

#pragma WKUIDelegate
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    if ([message.name isEqualToString:@"AppCtx"]) {
        NSMutableDictionary * etc = [[NSMutableDictionary alloc] initWithDictionary:@{@"class":self}];
        //        [etc setDictionary:message.body];
        [etc addEntriesFromDictionary:message.body];
        NSError *err = nil;
        NSData *data = [NSJSONSerialization dataWithJSONObject:message.body options:NSJSONWritingPrettyPrinted error:&err];
        if (err) {
            NSLog(@"[NSString] jsonObject error:%@",err);
        }
        NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"data:%@", s);
        //        NSDictionary * etc = [[NSDictionary alloc] initWithDictionary:message.body];
//        [[NSNotificationCenter defaultCenter] postNotificationName:etc[@"action"] object:nil userInfo:etc];
        [[BKHttpRequestManager defaultManager] getJSON:@"http://push-service-test.rongyiju.net/"
                                            parameters:@{@"data":s}
                                               success:^(id  _Nonnull task, id  _Nullable json) {
                                                   
                                               }
                                               failure:^(id  _Nullable task, id  _Nullable json, NSError * _Nonnull error) {
                                                   
                                               }];
    }
}
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
    
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    //    DLOG(@"msg = %@ frmae = %@",message,frame);
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
    }];
    [alertController addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
    }])];
    
    [self presentViewController:alertController animated:YES completion:nil];
}
- (WKWebView*)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
    if (!self.shouldCreateNewWindow) {
        [webView loadRequest:navigationAction.request];
    }
    return nil;
}
/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

- (void)dealloc {
    [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"AppCtx"];
    [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
    [_webView removeObserver:self forKeyPath:@"canGoBack"];
    [_webView removeObserver:self forKeyPath:@"canGoForward"];
}
@end
